﻿/************************************************************************************
* Copyright (c) 2019 All Rights Reserved.
*命名空间：Merge.BLL
*文件名： CaveControlModel
*创建人： Liebeskind
*创建时间：2019/6/25 14:54:07
*描述
*=====================================================================
*修改标记
*修改时间：2019/6/25 14:54:07
*修改人：Liebeskind
*描述：1.避免模组中断导致的仓数据错误，引入规则的方式
*       2.避免模组搬运中的时差导致虚位仓超规划等问题，引入规划的方式，所以虚位的搜索必须在规划值中实现
************************************************************************************/
using Commonality.DAL.MySQL;
//using Commonality.Model.CPLCControl;
using Commonality.Model;
using Commonality.Model.Classify;
using Commonality.Model.PLCControl;
using MathNet.Numerics.LinearAlgebra.Double;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Merge.BLL.Cave
{
    public enum CaverErr
    {
        Null = 0,
        DataAbn = 1
    }

    public class CaveModel
    {
        /// <summary>
        /// 仓号：A11->111，B21->221
        /// </summary>
        public int CaverModelNumber { get; set; }
        #region 特征
        /// <summary>
        /// 特征
        /// </summary>
        public CEigenvector Eigenvector;
        /// <summary>
        /// 特征
        /// </summary>
        public string sEigenvector { get; set; }
        /// <summary>
        /// 特征向量
        /// </summary>
        public DenseMatrix mEigenvector { get; set; }
        #endregion
        #region 规划值
        /// <summary>
        /// 特征实例规划量/cell；规划值
        /// </summary>
        public int ContProgramme { get; set; }

        /// <summary>
        /// 仓内产品SN集合；规划值
        /// </summary>
        public List<string> ListSNProgramme { get; set; }
        #endregion

        #region 实际值
        /// <summary>
        /// 特征实例实际量/cell
        /// </summary>
        public int Cont { get; set; }
        /// <summary>
        /// 未满仓等待时间/入仓等待超时间；实际值
        /// </summary>
        public int AwaitTime { get; set; }
        /// <summary>
        /// 仓内产品SN集合；实际值
        /// </summary>
        public List<string> ListSN { get; set; }
        #endregion

        #region 仓数据寄存


        #endregion

        #region IO
        /// <summary>
        /// 穴位对应的PLC内存单元
        /// </summary>
        public TPLCCell CavePLCMemory_PLC;
        /// <summary>
        /// 仓所属模组运动状态
        /// </summary>
        public TPLCCell HandLeisure_PLC;
        /// <summary>
        /// 仓目前的物理操作
        /// </summary>
        public TPLCCell CaveStuation_PLC;
        /// <summary>
        /// 所属模组模组位置寄存器
        /// </summary>
        public TPLCCell Destination_PLC;
        /// <summary>
        /// 所属模组取料结点命令寄存器
        /// </summary>
        public TPLCCell Node_PLC;
        #endregion

        #region 时计
        /// <summary>
        /// 超时时间
        /// </summary>
        public TPLCCell OldTime;

        /// <summary>
        /// 未满仓等待时间/入仓等待超时间；规划值
        /// </summary>
        public static double AwaitTimeProgramme { get; set; }

        /// <summary>
        /// 超时定时器启用/停止-本地
        /// </summary>
        public bool OldTimeFuncTrigger { get; set; }

        /// <summary>
        /// 超时定时器启用/停止-全局
        /// </summary>
        public static bool AllOldTimeFuncTrigger { get; set; }
        /// <summary>
        /// 超时定时器启用/停止-全局
        /// </summary>
        public static bool AOldTimeFuncTrigger { get; set; }
        /// <summary>
        /// 超时定时器启用/停止-全局
        /// </summary>
        public static bool BOldTimeFuncTrigger { get; set; }
        #endregion

        #region 仓状态属性
        /////////////////////////////////////////////值////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 仓实际存量
        /// </summary>
        public int staCavePLCMemory;
        /// <summary>
        /// 仓所属模组状态
        /// </summary>
        public int staHandLeisure;
        /// <summary>
        /// 仓物理状态
        /// </summary>
        public int staCaveStuation;
        /// <summary>
        /// 仓所属模组目标
        /// </summary>
        public int staDestination;
        /// <summary>
        /// 仓进仓超时
        /// </summary>
        public uint staCaverOldTime;


        ///////////////////////////////////////////////标签//////////////////////////////////////////////////////////
        /// <summary>
        /// 仓是否空闲
        /// </summary>
        public bool isLeisure;
        #endregion

        #region 标志
        private bool IntoFlag;

        /// <summary>
        /// 正常打包出仓中
        /// </summary>
        private bool OkOutIngFlag;

        /// <summary>
        /// 捕获注册仓的脉冲
        /// </summary>
        private bool RegisterPulsating;
        #endregion

        #region 仓的异常标志
        /// <summary>
        /// 仓的异常状态
        /// </summary>
        public CaverErr caverErr;
        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="number"></param>
        /// <param name="tPLCCell"></param>
        /// <param name="handLeisure"></param>
        /// <param name="caveStuation"></param>
        public CaveModel(int number, TPLCCell tPLCCell, TPLCCell handLeisure, TPLCCell caveStuation, TPLCCell Destination, TPLCCell Node, TPLCCell Time)
        {
            #region 初始化            
            ListSNProgramme = new List<string>();
            ListSN = new List<string>();
            #endregion

            CaverModelNumber = number;

            CPLCControl.InitPlcCell(out CavePLCMemory_PLC, tPLCCell.sigType, tPLCCell.stationNumber, tPLCCell.addr, tPLCCell.offset);
            CPLCControl.InitPlcCell(out HandLeisure_PLC, handLeisure.sigType, handLeisure.stationNumber, handLeisure.addr, handLeisure.offset);
            CPLCControl.InitPlcCell(out CaveStuation_PLC, caveStuation.sigType, caveStuation.stationNumber, caveStuation.addr, caveStuation.offset);
            CPLCControl.InitPlcCell(out Destination_PLC, Destination.sigType, Destination.stationNumber, Destination.addr, Destination.offset);
            CPLCControl.InitPlcCell(out Node_PLC, Node.sigType, Node.stationNumber, Node.addr, Node.offset);

            CPLCControl.InitPlcCell(out OldTime, Time.sigType, Time.addr, Time.offset);

            Eigenvector = new CEigenvector(LINE.ZERO, "", KCAndBF.ZERO, Remark.ZERO, "","", "", "", "", "", "", "", DenseMatrix.OfArray(new[,] { { 0.0 }, { 0 }, { 0 }, { 0 } }));


            AwaitTimeProgramme = 2400;

            caverErr = CaverErr.Null;

            //CPLCControl.LAD_SetDblCell(CaveStuation_PLC,0);

            IntoFlag = false;

            OkOutIngFlag = false;
        }

        #region 仓初始化
        /// <summary>
        /// 仓启动前自检
        /// </summary>
        public void SelfInspection()
        {
            if (CPLCControl.LAD_GetDblCell_(CaveStuation_PLC) == 0)
            {
                //待操作时
                if (CaveCont() > ContProgramme / 2 && ListSN.Count == 0)
                {
                    //异常剔除
                    CPLCControl.LAD_SetDblCell_(CavePLCMemory_PLC, 100);
                    DataClearance();                                                                        //清空缓存数据
                    Log4Net.MsgInfo("llll");
                    caverErr = CaverErr.DataAbn;
                }
            }
            if (CPLCControl.LAD_GetDblCell_(CaveStuation_PLC) == 2)
            {
                if (CaveCont() > ContProgramme / 2)
                {
                    //异常剔除
                    CPLCControl.LAD_SetDblCell_(CavePLCMemory_PLC, 100);
                    DataClearance();                                                                        //清空缓存数据
                    Log4Net.MsgInfo("kkkk");
                    caverErr = CaverErr.DataAbn;

                    CPLCControl.LAD_SetDblCell_(CaveStuation_PLC, 0);
                }
            }

            if (CPLCControl.LAD_GetDblCell_(CaveStuation_PLC) == 2)
            {
                if (CaveCont() == 0 && ContProgramme == 0 && ListSN.Count == 0)
                {
                    CPLCControl.LAD_SetDblCell_(CaveStuation_PLC, 0);
                    Log4Net.MsgInfo("仓异常状态清除");
                }
            }
            if ((Eigenvector.PN == "" && (ListSNProgramme.Count != 0 || CPLCControl.LAD_GetDblCell_(CavePLCMemory_PLC) != 0)))
            {
                //异常剔除
                CPLCControl.LAD_SetDblCell_(CavePLCMemory_PLC, 100);
                DataClearance();                                                                        //清空缓存数据
                Log4Net.MsgInfo("fffff");
                caverErr = CaverErr.DataAbn;

                CPLCControl.LAD_SetDblCell_(CaveStuation_PLC, 0);
            }


            CPLCControl.LAD_SetTCell_(OldTime, (uint)AwaitTimeProgramme);           //初始化超时定时器

            CaverLabel();
        }
        #endregion

        #region 公共方法
        /// <summary>
        /// 获取仓实际存量/Tray
        /// </summary>
        /// <returns></returns>
        public int CaveCont()
        {
            return CPLCControl.LAD_GetDblCell_(CavePLCMemory_PLC);
        }
        #endregion

        #region 入仓
        /// <summary>
        /// 规划入仓：唯一操作规划值
        /// </summary>
        /// <param name="SNia"></param>
        /// <param name="SNib"></param>
        public void ProgrammeWarehousing(string SNia, string SNib, ref byte flag)
        {
            if (ListSN.Count() < 20 && CPLCControl.LAD_GetDblCell_(CaveStuation_PLC) == 0 && CPLCControl.LAD_GetDblCell_(Destination_PLC) == 0)
            {
                //if (ListSNProgramme.Count > ListSN.Count)
                //{
                //    //规划值存在未被执行的情况：考虑物理动作被中断导致，清除待规划值，再添加新规划
                //    ListSNProgramme.RemoveRange(ListSNProgramme.Count - 2, 2);
                //}
                //防呆
                if (!ListSN.Contains(SNia) && !ListSN.Contains(SNib) || true)
                {
                    //避免重复

                    //存入规划缓存
                    CaverBuffData.ProgrammeWarehousingWriteBuffer(CaverModelNumber, ListSNProgramme.Count, SNia, SNib);
                    //刷新规划
                    ListSNProgramme.Add(SNia);
                    ListSNProgramme.Add(SNib);
                    ContProgramme = ListSNProgramme.Count;
                    CPLCControl.LAD_SetDblCell_(Destination_PLC, (short)(CaverModelNumber % 10));
                    Log4Net.MsgInfo(CaverModelNumber + "仓" + Eigenvector.PN + "入仓");
                    //CPLCControl.LAD_SetDblCell_(Node_PLC, 0);            //开始规划入仓，取料复位结点变量
                    flag = 0;
                }

            }
            else if (CPLCControl.LAD_GetDblCell_(CaveStuation_PLC) != 0)
            {

            }
            else if (CPLCControl.LAD_GetDblCell_(Destination_PLC) != 0)
            {

            }

        }


        /// <summary>
        /// 规划入仓：唯一操作规划值
        /// </summary>
        /// <param name="SNia"></param>
        /// <param name="SNib"></param>
        public void ProgrammeWarehousing_(string SNia, string SNib)
        {
            if (ListSN.Count() < 20 /*&& CPLCControl.LAD_GetDblCell_(CaveStuation_PLC) == 0*/ && CPLCControl.LAD_GetDblCell_(Destination_PLC) == 0)
            {
                //if (ListSNProgramme.Count > ListSN.Count)
                //{
                //    //规划值存在未被执行的情况：考虑物理动作被中断导致，清除待规划值，再添加新规划
                //    ListSNProgramme.RemoveRange(ListSNProgramme.Count - 2, 2);
                //}
                //防呆
                if (!ListSN.Contains(SNia) && !ListSN.Contains(SNib))
                {
                    //避免重复

                    //存入规划缓存
                    CaverBuffData.ProgrammeWarehousingWriteBuffer(CaverModelNumber, ListSNProgramme.Count, SNia, SNib);
                    //刷新规划
                    ListSNProgramme.Add(SNia);
                    ListSNProgramme.Add(SNib);
                    ContProgramme = ListSNProgramme.Count;
                    Log4Net.MsgInfo(CaverModelNumber + "仓" + Eigenvector.PN + "入仓" + "\r\nSN1：" + SNia + "\r\nSN2：" + SNib);

                }

            }
            else if (CPLCControl.LAD_GetDblCell_(CaveStuation_PLC) != 0)
            {

            }
            else if (CPLCControl.LAD_GetDblCell_(Destination_PLC) != 0)
            {

            }

        }

        /// <summary>
        /// 实际入仓操作：被主线自动轮询
        /// </summary>
        public void PracticalWarehousing()
        {
            int cont = CPLCControl.LAD_GetDblCell_(CavePLCMemory_PLC);
            int sta = CPLCControl.LAD_GetDblCell_(CaveStuation_PLC);
            //TODO:模拟测试

            if (sta == 0)
            {
                IntoFlag = false;
            }

            if (sta == 2 && !IntoFlag)
            {
                if (cont > 0)
                {
                    if (cont * 2 == ListSNProgramme.Count)
                    {
                        //仓实际数量达到规划值
                        if (!ListSN.Contains(ListSNProgramme[ListSNProgramme.Count - 2]) && !ListSN.Contains(ListSNProgramme[ListSNProgramme.Count - 1]))
                        {
                            //避免重复

                            //存入实际缓存
                            CaverBuffData.PracticalWarehousingWriteBuffer(CaverModelNumber, ListSNProgramme.Count - 2,
                                                                            ListSNProgramme[ListSNProgramme.Count - 2],
                                                                            ListSNProgramme[ListSNProgramme.Count - 1]);

                            CaverBuffData.PracticalWarehousingWriteBufferAction.BeginInvoke(CaverModelNumber, ListSNProgramme.Count - 2,
                                                                            ListSNProgramme[ListSNProgramme.Count - 2],
                                                                            ListSNProgramme[ListSNProgramme.Count - 1], null, null);
                            //刷新实际值
                            ListSN.Add(ListSNProgramme[ListSNProgramme.Count - 2]);
                            ListSN.Add(ListSNProgramme[ListSNProgramme.Count - 1]);
                            Cont = ContProgramme;

                            CPLCControl.LAD_SetDblCell_(CaveStuation_PLC, 0);
                            #region 重置定时器
                            CPLCControl.LAD_ResetCell_(OldTime);
                            CPLCControl.LAD_SetTCell_(OldTime, (uint)AwaitTimeProgramme);
                            #endregion

                            IntoFlag = true;
                        }
                        Log4Net.MsgInfo(CaverModelNumber + "仓实际数量" + cont + "规划数量" + (ListSNProgramme.Count / 2));
                    }
                    else
                    {

                    }
                }
            }

            return;

        }
        /// <summary>
        /// 入仓呆滞超时轮询
        /// </summary>
        public void StandbyTime()
        {
            if (CPLCControl.LAD_CheckCell_(OldTime) == 1)
            {
                if ((CPLCControl.LAD_GetDblCell_(CavePLCMemory_PLC) == ListSNProgramme.Count / 2 && CPLCControl.LAD_GetDblCell_(CavePLCMemory_PLC) > 0 && ListSNProgramme.Count != 20) ||
                    (Eigenvector.PN != "" && ListSNProgramme.Count == 0) ||
                    (Eigenvector.PN == "" && (ListSNProgramme.Count != 0 || CPLCControl.LAD_GetDblCell_(CavePLCMemory_PLC) != 0)) ||
                    (ListSNProgramme.Count == 20 && CPLCControl.LAD_GetDblCell_(CavePLCMemory_PLC) != 10 && CPLCControl.LAD_GetDblCell_(CaveStuation_PLC) == 0))
                {
                    CPLCControl.LAD_ResetCell_(OldTime);
                    CPLCControl.LAD_SetTCell_(OldTime, (uint)AwaitTimeProgramme);

                    if (CaverModelNumber < 200)
                    {
                        if (AOldTimeFuncTrigger)
                        {
                            #region 仓超时方法
                            Log4Net.MsgInfo(CaverModelNumber + "仓等待超时，自动清仓。");
                            CPLCControl.LAD_SetDblCell_(CavePLCMemory_PLC, 100);
                            try
                            {
                                if (ListSN[0] != null)
                                {
                                    MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSN[0], 31, "缓存仓内呆滞超时摞", null, null);
                                }
                            }
                            catch
                            {
                            }
                            try
                            {
                                MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSNProgramme[0], 31, "缓存仓内呆滞超时摞", null, null);

                            }
                            catch
                            {
                            }
                            DataClearance();
                            #endregion
                        }
                        else
                        {
                            //Log4Net.MsgInfo(CaverModelNumber + "仓超时方法未启用");
                        }
                    }
                    else
                    {
                        if (BOldTimeFuncTrigger)
                        {
                            #region 仓超时方法
                            Log4Net.MsgInfo(CaverModelNumber + "仓等待超时，自动清仓。");
                            CPLCControl.LAD_SetDblCell_(CavePLCMemory_PLC, 100);
                            try
                            {
                                if (ListSN[0] != null)
                                {
                                    MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSN[0], 31, "缓存仓内呆滞超时摞", null, null);
                                }
                            }
                            catch
                            {
                            }
                            try
                            {
                                MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSNProgramme[0], 31, "缓存仓内呆滞超时摞", null, null);

                            }
                            catch
                            {
                            }
                            DataClearance();
                            #endregion
                        }
                        else
                        {
                            //Log4Net.MsgInfo(CaverModelNumber + "仓超时方法未启用");
                        }
                    }


                }
                else
                {
                    CPLCControl.LAD_ResetCell_(OldTime);
                    CPLCControl.LAD_SetTCell_(OldTime, (uint)AwaitTimeProgramme);
                    //Log4Net.MsgInfo(CaverModelNumber + "仓等待超时计时器重置。");

                }
            }


            #region 特别的：存在注册空仓后未完成实际入仓导致存在仓只被注册完成不了打包自动清仓致使“空仓”被占用
            if (Eigenvector.PN != ""&& ListSNProgramme.Count == 0)
            {
                //被注册，却一直未被规划入仓，超过一分钟后自动注销注册（注册仓时，亦会刷新超时定时器）
                if (CPLCControl.LAD_CheckTimeCell(OldTime) >60)
                {
                    Log4Net.MsgInfo(CaverModelNumber + "仓只被注册，未进行过入仓规划，注销此空仓！");
                    CPLCControl.LAD_SetDblCell_(CavePLCMemory_PLC, 100);
                    DataClearance();
                    CPLCControl.LAD_ResetCell_(OldTime);
                    CPLCControl.LAD_SetTCell_(OldTime, (uint)AwaitTimeProgramme);
                }
            }
            #endregion
        }


        #endregion

        #region 清仓
        /// <summary>
        /// 手动清仓
        /// </summary>
        /// <param name="process">手动清仓摞的目的地设置</param>
        public bool CaveForceEmpty(int process)
        {
            if (CPLCControl.LAD_CheckCell(HandLeisure_PLC) == 1)
            {
                return false;
            }
            else
            {
                CPLCControl.LAD_SetDblCell(CavePLCMemory_PLC, 100);
                switch (process)
                {
                    case 0:
                        //
                        MySqlFunction.PackageOrientation.PackageOrientation_UPDATE(ListSN[0], 0, "OK");         //自动区未满箱包装
                        break;
                    case 1:
                        //
                        MySqlFunction.PackageOrientation.PackageOrientation_UPDATE(ListSN[0], 1, "");
                        break;
                    case 2:
                        //
                        MySqlFunction.PackageOrientation.PackageOrientation_UPDATE(ListSN[0], 2, "");
                        break;
                    case 3:
                        //
                        MySqlFunction.PackageOrientation.PackageOrientation_UPDATE(ListSN[0], 3, "");
                        break;
                    default:
                        break;
                }
                return true;
            }
        }
        /// <summary>
        /// 自动清仓的处理，被主线轮询,一摞的打包
        /// </summary>
        public void CaveFullEmpty_AutoFunc()
        {
            int cont = CPLCControl.LAD_GetDblCell_(CavePLCMemory_PLC);
            //int cont = CPLCControl.LAD_GetDblCell(CavePLCMemory_PLC);
            int pro = ListSNProgramme.Count;
            int pra = ListSN.Count;
            int sta = CPLCControl.LAD_GetDblCell_(CaveStuation_PLC);
            //TODO:模拟测试
            if (sta == 1)
            {
                //出仓操作
                if (cont == Cont / 2 && cont == 10 && pro / 2 == 10 && pra / 2 == 10)
                {
                    //实际达到目标规划,非未满
                    MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSN[0], 24, "OK", null, null);         //自动区满料包装，更新流程表
                    MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSNProgramme[0], 24, "OK", null, null);         //自动区满料包装，更新流程表
                    MySqlFunction.PacketData.PacketData_INSERT_Action(ListSN, CaverModelNumber.ToString());                                     //打包数据存入数据库   
                    //PacketDataErasure.PacketDataErasureCellAdd(ListSN[0], -10);
                    PacketDataErasure.PacketDataErasureCellAddAction2.BeginInvoke(ListSN[0], -25, null, null);     //包数据开始擦除计时
                    Eigenvector = new CEigenvector(LINE.ZERO, "", KCAndBF.ZERO, Remark.ZERO, "","", "", "", "", "", "", "", DenseMatrix.OfArray(new[,] { { 0.0 }, { 0 }, { 0 }, { 0 } })); //复位仓的特征
                    DataClearance();                                                                        //清空缓存数据
                    CPLCControl.LAD_SetDblCell_(CaveStuation_PLC, 0);
                    OkOutIngFlag = true;
                    Log4Net.MsgInfo(CaverModelNumber + "仓完成打包，准备出仓");
                }
                else if (cont == 0 && pro == 0 && pra == 0)
                {
                    //TODU: 待解决
                    //仓内实际空 - 错误出仓状态 - 复位数据
                    CPLCControl.LAD_SetDblCell_(CaveStuation_PLC, 0);
                    //DataClearance();
                    Log4Net.MsgInfo(CaverModelNumber + "仓内实际对象数量为" + cont + "错误出仓状态,清除规划数据");

                }
                else
                {

                }
            }
            else if (sta == 0)
            {
                if (OkOutIngFlag)
                {
                    //出仓进行中。。。
                    if (cont == 0)
                    {
                        //出仓完成PLC清空实际产品计数
                        OkOutIngFlag = false;
                        Log4Net.MsgInfo(CaverModelNumber + "完成出仓");
                    }

                }
                else
                {
                    //非出仓进行中
                    //待操作时
                    if (cont > ContProgramme / 2 && ListSN.Count > 0)
                    {
                        Log4Net.MsgInfo("cont:" + cont + "//" + "ContProgramme:" + ContProgramme + "//" + "sta:" + sta);
                        //异常剔除
                        try
                        {
                            MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSN[0], 4, "分类仓异常对象", null, null);         //自动区满料包装，更新流程表

                        }
                        catch
                        {
                        }
                        try
                        {
                            MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSNProgramme[0], 4, "分类仓异常对象", null, null);         //自动区满料包装，更新流程表

                        }
                        catch
                        {
                        }
                        CPLCControl.LAD_SetDblCell_(CavePLCMemory_PLC, 100);
                        DataClearance();                                                                        //清空缓存数据
                        Log4Net.MsgInfo(CaverModelNumber + "仓内实际对象数" + cont + "超过规划值" + (ContProgramme / 2));
                    }

                    if (cont * 2 - ContProgramme > 2 || ContProgramme - cont * 2 > 2)
                    {
                        Log4Net.MsgInfo("cont:" + cont + "//" + "ContProgramme:" + ContProgramme + "//" + "sta:" + sta);
                        //实际入仓少于规划（2：排除规划实现中实际值比规划值少1的情况）
                        //异常剔除
                        try
                        {
                            MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSN[0], 4, "分类仓异常对象", null, null);         //自动区满料包装，更新流程表

                        }
                        catch
                        {
                        }
                        try
                        {
                            MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSNProgramme[0], 4, "分类仓异常对象", null, null);         //自动区满料包装，更新流程表

                        }
                        catch
                        {
                        }
                        CPLCControl.LAD_SetDblCell_(CavePLCMemory_PLC, 100);
                        DataClearance();                                                                        //清空缓存数据
                        Log4Net.MsgInfo(CaverModelNumber + "仓内实际对象数" + cont + "规划值" + (ContProgramme / 2) + "存在规划未实现");
                    }

                }
            }
            else if (sta == 2)
            {
                if (cont * 2 - ContProgramme > 2 || ContProgramme - cont * 2 > 2)
                {
                    Log4Net.MsgInfo("cont:" + cont + "//" + "ContProgramme:" + ContProgramme + "//" + "sta:" + sta);
                    //异常剔除
                    try
                    {
                        MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSN[0], 4, "分类仓异常对象", null, null);         //自动区满料包装，更新流程表

                    }
                    catch
                    {
                    }
                    try
                    {
                        MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSNProgramme[0], 4, "分类仓异常对象", null, null);         //自动区满料包装，更新流程表

                    }
                    catch
                    {
                    }
                    CPLCControl.LAD_SetDblCell_(CavePLCMemory_PLC, 100);
                    DataClearance();                                                                        //清空缓存数据
                    Log4Net.MsgInfo(CaverModelNumber + "仓内实际对象数" + cont + "规划值" + (ContProgramme / 2) + "存在规划未实现");

                    CPLCControl.LAD_SetDblCell_(CaveStuation_PLC, 0);
                }
                else if (ContProgramme == 0)
                {
                    //异常剔除
                    try
                    {
                        MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSN[0], 4, "分类仓异常对象", null, null);         //自动区满料包装，更新流程表

                    }
                    catch
                    {
                    }
                    try
                    {
                        MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSNProgramme[0], 4, "分类仓异常对象", null, null);         //自动区满料包装，更新流程表

                    }
                    catch
                    {
                    }
                    CPLCControl.LAD_SetDblCell_(CavePLCMemory_PLC, 100);
                    DataClearance();                                                                        //清空缓存数据
                    Log4Net.MsgInfo(CaverModelNumber + "仓内实际对象数" + cont + "规划值" + (ContProgramme / 2) + "规划异常");

                    CPLCControl.LAD_SetDblCell_(CaveStuation_PLC, 0);
                }

            }
            else if (sta == 3)
            {

                try
                {
                    CPLCControl.LAD_SetDblCell_(CaveStuation_PLC, 0);
                    //下位机异常清仓
                    try
                    {
                        MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSN[0], 4, "分类仓异常对象", null, null);         //自动区满料包装，更新流程表

                    }
                    catch
                    {
                    }
                    try
                    {
                        MySqlFunction.PackageOrientation.PackageOrientation_UPDATE_Action.BeginInvoke(ListSNProgramme[0], 4, "分类仓异常对象", null, null);         //自动区满料包装，更新流程表

                    }
                    catch
                    {
                    }

                    if (ListSNProgramme.Count == ListSN.Count)
                    {
                        //发生异常时，取料点没有待实现的规划//
                        DataClearance();
                        Log4Net.MsgInfo(CaverModelNumber + "下位机异常清仓");
                    }
                    else if (ListSNProgramme.Count - ListSN.Count == 2)
                    {
                        //发生异常时，取料点存在规划待实现//
                        Cont = 0;                           //清除实际数量
                        ContProgramme = 0;                  //更新规划数量
                        string sna = ListSNProgramme[ListSNProgramme.Count - 2];
                        string snb = ListSNProgramme[ListSNProgramme.Count - 1];            //提出规划

                        //提出待实现的规划-重新从零开始实现规划
                        ListSNProgramme.Clear();
                        ListSN.Clear();
                        CaverBuffData.ProgrammeWarehousingWriteBuffer(CaverModelNumber, ListSNProgramme.Count, sna, snb);       //更新规划缓存
                        ListSNProgramme.Add(sna);
                        ListSNProgramme.Add(snb);
                        ContProgramme = ListSNProgramme.Count;
                        CaverBuffData.BufferDataClearance(CaverModelNumber);                //清除实现缓存
                        Log4Net.MsgInfo(CaverModelNumber + "下位机异常清仓-同时存在带规划待实现");
                    }
                }
                catch (Exception)
                {

                }


            }

        }

        private readonly object DataClearanceLock = new object();
        /// <summary>
        /// 清仓的数据方法
        /// </summary>
        public void DataClearance()
        {
            Cont = 0;
            ContProgramme = 0;
            sEigenvector = "";
            ListSNProgramme.Clear();
            Eigenvector = new CEigenvector(LINE.ZERO, "", KCAndBF.ZERO, Remark.ZERO, "","", "", "", "", "", "", "", DenseMatrix.OfArray(new[,] { { 0.0 }, { 0 }, { 0 }, { 0 } })); //复位仓的特征
            ListSN.Clear();
            CaverBuffData.BufferDataClearance(CaverModelNumber);
            Log4Net.MsgInfo(CaverModelNumber + "仓清数据");
        }
        /// <summary>
        /// 物理清仓方法
        /// </summary>
        public void CaverPhyClear()
        {
            CPLCControl.LAD_SetDblCell(CavePLCMemory_PLC, 100);
        }
        #endregion


        #region 仓状态标志
        public void CaverSta()
        {
            staCavePLCMemory = CPLCControl.LAD_GetDblCell_(CavePLCMemory_PLC);
            staCaveStuation = CPLCControl.LAD_GetDblCell_(CaveStuation_PLC);
            staDestination = CPLCControl.LAD_GetDblCell_(Destination_PLC);
            staHandLeisure = CPLCControl.LAD_GetDblCell_(HandLeisure_PLC);
            staCaverOldTime = CPLCControl.LAD_CheckTimeCell(OldTime);
            CaverLabel();
            CaverRegisterPulsating();
        }
        /// <summary>
        /// 仓的状态属性-标签
        /// </summary>
        private void CaverLabel()
        {
            //仓是否空闲中
            isLeisure = (CaveCont() == 0 && Eigenvector.PN == "" && CPLCControl.LAD_GetDblCell_(CaveStuation_PLC) == 0);
        }
        #endregion
        #region 仓的自维护
        #region 捕获仓被注册的瞬间
        /// <summary>
        /// 捕获注册的瞬间
        /// </summary>
        private void CaverRegisterPulsating()
        {
            if (Eigenvector.PN == "")
            {
                RegisterPulsating = false;
            }

            if (Eigenvector.PN != "" && !RegisterPulsating)
            {
                RegisterPulsating = true;
                BeRegisteredEmptyCaverCancelOldTimeSta();
            }
        }
        #endregion

        #region 方法
        /// <summary>
        /// 注册到第一块入仓前也需要超时计时-刷新定时器
        /// </summary>
        private void BeRegisteredEmptyCaverCancelOldTimeSta()
        {
            CPLCControl.LAD_ResetCell_(OldTime);
            CPLCControl.LAD_SetTCell_(OldTime, (uint)AwaitTimeProgramme);
        }
        #endregion

        #endregion
    }

    public class CaveGroupModel
    {

    }
}
